
package jason.asSyntax.directives;

import jason.asSemantics.Agent;
import jason.asSyntax.*;
import jason.asSyntax.parser.ParseException;
import jason.asSyntax.parser.Token;
import jason.asSyntax.parser.as2j;
import jason.util.Util.Pair;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/** Implementation of the <code>include</code> directive. */
public class Include implements Directive {
	private static Logger logger = Logger.getLogger(Include.class.getName());
	
	public Agent process(Atom directive, Agent outerContent, Agent innerContent, Token token) {
		if (outerContent == null) return null;
		
		String reference = '[' + directive.getErrorMsg() + "] ";
		
		if(directive.getArity() <= 0) {
			throw new RuntimeException("", new ParseException(reference + "The include directive must have 1 argument!\n\t(It is being invoked in the agent '" + outerContent.getASLSrc() + "'.)", token));
		}
		if(!directive.getTerm(0).isString()) {
			throw new RuntimeException("", new ParseException(reference + "The first argument of the include directive is meant to be a string!\n\t(It is being invoked in the agent '" + outerContent.getASLSrc() + "'.)", token));
		}
		
		String path = ((StringTerm)directive.getTerm(0)).getString();
		Pair<String, InputStream> absPathAndStream;
		try {
			absPathAndStream = Import.getAbsPathAndStream(outerContent.getASLSrc(), path, true);
		} catch (FileNotFoundException e) {
			throw new RuntimeException("", new ParseException(reference + "The included file '" + path + "' was not found!\n\t(It is being included in the agent '" + outerContent.getASLSrc() + "'.)", token));
		} catch (Exception e) {
			throw new RuntimeException("", new ParseException(reference + "The included file '" + path + "' could not be loaded!\n\t" + e.toString() + "\n\t(It is being included in the agent '" + outerContent.getASLSrc() + "'.)", token));
		}
		
		path = absPathAndStream.fst;
		InputStream in = absPathAndStream.snd;
		
		try {
			Agent ag = new Agent();
			ag.initAg();
			ag.setAsSameForModuleSystem(outerContent);
			ag.setASLSrc(path);
			as2j parser = new as2j(in);
			
			parser.agent(ag);
			
			logger.fine("as2j: AgentSpeak program '" + path + "' parsed successfully!");
			return ag;
		} catch (Exception e) {
			throw new RuntimeException("in included file \"" + path + "\": ", e);
		}
	}
}
